<?php

/*
 * This script belongs to Aspect PHP.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This script is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 */

require_once dirname(__FILE__) . '/../bootstrap.php';
require_once dirname(__FILE__) . '/../aspect/Foo.class.php';
require_once dirname(__FILE__) . '/../aspect/FooAspect.class.php';
require_once dirname(__FILE__) . '/../aspect/TestingValue.class.php';

/**
 * Test class for aspectContainer
 *
 * @package    aspectPhp
 * @subpackage test
 * @author     gboisse
 */
class aspectContainerTest extends PHPUnit_Framework_TestCase {

    /**
     * @var aspectContainer
     */
    protected static $aspectContainer;

    public static function setUpBeforeClass() {
        self::$aspectContainer = new aspectContainer();
    }

    public function testBeforeAdvice_successful() {
        self::$aspectContainer->doBefore('method(Foo->doSomeStuff())', 'FooAspect', 'myBeforeAdvice');

        $testingValue = new TestingValue();

        $foo = new aspectProxy(new Foo());
        $result = $foo->doSomeStuff($testingValue);

        $this->assertNotNull($result);
        $this->assertEquals('BeforeAdvice:Target', $testingValue->getTestingValue());
    }

    public function testAfterAdvice_successful() {
        self::$aspectContainer->doAfter('method(F.*o->do.*())', 'FooAspect', 'myAfterAdvice');

        $testingValue = new TestingValue();

        $foo = new aspectProxy(new Foo());
        $result = $foo->doSomeStuff($testingValue);

        $this->assertNotNull($result);
        $this->assertEquals('BeforeAdvice:Target:AfterAdvice', $testingValue->getTestingValue());
    }

    public function testAroundAdvice_successful() {
        self::$aspectContainer->doAround('method(F.*->.*f())', 'FooAspect', 'myAroundAdvice');

        $testingValue = new TestingValue();

        $foo = new aspectProxy(new Foo());
        $result = $foo->doSomeStuff($testingValue);

        $this->assertNull($result);
        $this->assertEquals('BeforeAdvice:Around:AfterAdvice', $testingValue->getTestingValue());
    }

    public function testAfterAdvice_notSuccessful() {
        self::$aspectContainer->doAfter('method(Fo.*->doSo.*Stuff())', 'FooAspect', 'myAfterAdvice2');

        $testingValue = new TestingValue();

        $foo = new aspectProxy(new Foo());

        $this->setExpectedException('RuntimeException',
                'Aspect unable to call FooAspect->myAfterAdvice2()!');
        $foo->doSomeStuff($testingValue);
    }

    public function testAspectContainer_notSuccessful() {
        $this->setExpectedException('LogicException',
                'Cannot instantiate two aspect containers!');
        $aspectContainer = new aspectContainer();
    }

}
